feat(pokestop): consume Golbat /api/pokestop/available with endpoint-authoritative fallback (draft)#1227
Draft
jfberry wants to merge 7 commits into
Draft
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pure, dependency-free mapper that reproduces Pokestop.js's SQL-derived
{ available, conditions } filter-key shape from the structured tuples
returned by Golbat's GET /api/pokestop/available, so a future endpoint
consumer can replace the SQL block key-for-key.
…tardust Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wires Pokestop.getAvailable() to Golbat's GET /api/pokestop/available
when a source has `mem` set (an endpoint source), using the Task 2
mapper to build the same {available, conditions} shape the SQL path
produces. Falls back to the existing SQL block unchanged on a
non-2xx response, a network/timeout error, or any thrown error;
MAD/DB sources (mem: '') skip the branch entirely and always run SQL.
Extracts the config-gated `fallbackRocketPokemonFiltering` a${id}-${form}
backfill (previously inline in the SQL rocketPokemon case) into a shared
applyRocketPokemonFallback() helper so both the endpoint and SQL paths
stay byte-identical. Adds a Pokestop.evalQuery static mirroring
Pokemon.evalQuery, since Pokestop extends Model directly and had no
endpoint-fetch helper of its own.
… SQL fallback path)
Endpoint sources (mem truthy) have no bound knex, so on
/api/pokestop/available failure the previous fallthrough to the SQL
block threw on this.query(), was swallowed by Promise.allSettled, and
silently contributed zero filter keys. Endpoint sources are now
endpoint-authoritative: on failure they return a clean empty
{ available: [], conditions: {} } instead of falling through, matching
Pokemon.getAvailable. The SQL block is reached only for mem:'' (DB/MAD)
sources.
Author
|
Status of this branch: does not operate in its current form as only the get available branch is ready; examining whether we should implement other api calls for pokestops here, or whether to allow a hybrid option |
A source with both a Golbat endpoint and DB creds now registers the endpoint AND builds a knex connection: migrated queries (Pokestop getAvailable) use the endpoint, un-migrated ones (getAll/getOne/search/ submissions) fall back to this.query() on the bound DB — so a Golbat pokestop endpoint no longer breaks map markers/popups/search. - DbManager: keep the knex connection for endpoint schemas that also carry DB creds; overlay mem/secret/httpAuth onto the schemaChecked context so isMad/has* flags survive. - Pokestop.getAvailable: on endpoint failure fall through to the SQL block (a dual source runs it on the bound knex; a pure-endpoint source throws and is dropped by allSettled) instead of returning empty. - types: ApiEndpoint.httpAuth typed; DbConnection gains optional endpoint/secret/httpAuth for the dual shape. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a ReactMap consumer for Golbat's new
GET /api/pokestop/available(Golbat draft PR UnownHash/Golbat#383). A scanner source that has a Golbatendpointnow fetches the pokestop filter/available list from Golbat instead of running ~30DISTINCT/GROUP BYSQL queries every 15 minutes — mirroring howPokemon.getAvailablealready consumes/api/pokemon/available. Everything else about pokestops (map markers, popups, search, submissions) is unchanged.A source can now be dual (
endpoint+ DB creds): the migrated query (getAvailable) uses the endpoint, while un-migrated queries fall back tothis.query()on the bound DB — so a Golbat pokestop endpoint is safe to enable without touching those features.How it works
server/src/models/pokestopAvailableMapper.js(new) — a pure mapper reproducing the SQL path's filter-key formulas exactly (quest rewardsq/d/p/m/c/x/u+ pokémon, invasionsi/b, confirmed rocketa, luresl, showcasesf/h, plus per-rewardconditions). Itsprocess()helper is byte-identical to the SQL path's.Pokestop.getAvailablewiring — anif (mem)endpoint branch that fetches, validates the response shape, and maps it. On failure (503 /fort_in_memoryoff, network error) it falls through to the SQL block: a dual source runs the SQL fallback on its bound knex; a pure-endpoint source has no knex, so it's dropped by the caller'sPromise.allSettled.DbManager) — a schema carrying bothendpointand DB creds registers the endpoint and builds a knex connection; the endpoint context (mem/secret/httpAuth) is overlaid onto the schema-checked DB context. Migrated methods readmem; un-migrated ones use the bound DB. Pure-endpoint and pure-DB schemas behave exactly as before.applyRocketPokemonFallback(shared helper) — the config-derived rocket-pokémona-keys (fromstate.event.invasions[*].encounters, gated byfallbackRocketPokemonFiltering, default on) are emitted from one helper used by both the SQL and endpoint paths, so those keys are identical by construction.AvailablePokestops(+ members);ApiEndpoint.httpAuthtyped;DbConnectiongains optionalendpoint/secret/httpAuthfor the dual shape.Configuring & testing
Requires the Golbat side up:
[general] fort_in_memory = trueand the APIsecretmatching ReactMap's. Sanity-check Golbat directly:Most instances already run Golbat for pokémon: a scanner DB source serving
["gym","pokestop","spawnpoint",...]plus a separate pure-endpoint golbat source for["pokemon","device"]. To route the pokestop available list through Golbat while keeping pokestop markers/popups/search on the DB, just add the two endpoint fields to your existing scanner DB source (the one whoseuseForincludespokestop):That's the whole change — the source becomes dual. Only pokestop consumes the endpoint (
getAvailable); gym/station/etc. don't checkmem, so they keep using the DB; and pokestop markers/popups/search/submissions fall back tothis.query()on the same DB. Your pure-endpoint pokémon source is untouched. (If you'd rather scope it tighter, split auseFor: ["pokestop"]-only copy of the DB source with the endpoint added and removepokestopfrom the original — but it isn't necessary.)Behavior:
/api/pokestop/available(offloads the ~30-query, 15-min SQL)getAvailablefalls back to SQL on the DBVerify: filter options populate and markers/popups/search still work; cross-check the filter list against your pre-change list (the
form_id 0/ type-20 golden check, on live data).Verification
Per maintainer preference, no test suite was added (this repo has none). Correctness was established by a line-by-line golden comparison of the mapper against the SQL key-building (all reward-type formulas, the
-formrule, theu-set,i/b, showcases, lures,with_armerge confirmed to match), throwaway sanity scripts, an end-to-end output-shape check (mapper output is structurally identical to the SQL return and consumed identically byDbManager.getAvailable+filters/builder/pokestop.js), andeslint/prettierclean (adding the dual-source types reduced the pre-existing tsc error count by one).Residual golden check (before enabling in prod)
Diff
mapAvailablePokestops(liveGolbatResponse)vs the SQLgetAvailableon the same data:form_id === 0→ bare<id>; type-20 real data (m<id>vsu20);a-key slot 2/3 whenfallbackRocketPokemonFilteringis off. If any diverge, the cleaner fix is Golbat-side (convey null form / a type-20 sentinel) — coordinate via #383.Follow-ups (deferred, non-blocking)
evalQueryutil —Pokestop.evalQueryis a ~47-line copy ofPokemon.evalQuery(task-scoping artifact).getOne(simple, endpoint exists) /getAll(complex, needs incidents added to Golbat's scan) to shave DB load — not needed for correctness thanks to the dual-source DB fallback.fetchJsonlogs the request payload (incl. base64 auth header) on every 503 — pre-existing, worth quieting.Depends on
Golbat UnownHash/Golbat#383 (the
/api/pokestop/availableendpoint). Draft until that lands and the golden check is run.🤖 Generated with Claude Code